// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This test suite uses SSLClientSocket to test the implementation of
// SSLServerSocket. In order to establish connections between the sockets
// we need two additional classes:
// 1. FakeSocket
//    Connects SSL socket to FakeDataChannel. This class is just a stub.
//
// 2. FakeDataChannel
//    Implements the actual exchange of data between two FakeSockets.
//
// Implementations of these two classes are included in this file.

#include "net/socket/ssl_server_socket.h"

#include <queue>
#include <stdint.h>
#include <stdlib.h>
#include <utility>

#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>

#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "crypto/nss_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
#include "crypto/signature_creator.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/mock_client_cert_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/socket/stream_socket.h"
#include "net/ssl/scoped_openssl_types.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
#include "net/ssl/ssl_private_key.h"
#include "net/ssl/ssl_server_config.h"
#include "net/ssl/test_ssl_private_key.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace net {

namespace {

    const char kClientCertFileName[] = "client_1.pem";
    const char kClientPrivateKeyFileName[] = "client_1.pk8";
    const char kWrongClientCertFileName[] = "client_2.pem";
    const char kWrongClientPrivateKeyFileName[] = "client_2.pk8";
    const char kClientCertCAFileName[] = "client_1_ca.pem";

    class MockCTVerifier : public CTVerifier {
    public:
        MockCTVerifier() = default;
        ~MockCTVerifier() override = default;

        int Verify(X509Certificate* cert,
            const std::string& stapled_ocsp_response,
            const std::string& sct_list_from_tls_extension,
            ct::CTVerifyResult* result,
            const BoundNetLog& net_log) override
        {
            return net::OK;
        }

        void SetObserver(Observer* observer) override { }
    };

    class MockCTPolicyEnforcer : public CTPolicyEnforcer {
    public:
        MockCTPolicyEnforcer() = default;
        ~MockCTPolicyEnforcer() override = default;
        ct::CertPolicyCompliance DoesConformToCertPolicy(
            X509Certificate* cert,
            const SCTList& verified_scts,
            const BoundNetLog& net_log) override
        {
            return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
        }

        ct::EVPolicyCompliance DoesConformToCTEVPolicy(
            X509Certificate* cert,
            const ct::EVCertsWhitelist* ev_whitelist,
            const SCTList& verified_scts,
            const BoundNetLog& net_log) override
        {
            return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS;
        }
    };

    class FakeDataChannel {
    public:
        FakeDataChannel()
            : read_buf_len_(0)
            , closed_(false)
            , write_called_after_close_(false)
            , weak_factory_(this)
        {
        }

        int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback)
        {
            DCHECK(read_callback_.is_null());
            DCHECK(!read_buf_.get());
            if (closed_)
                return 0;
            if (data_.empty()) {
                read_callback_ = callback;
                read_buf_ = buf;
                read_buf_len_ = buf_len;
                return ERR_IO_PENDING;
            }
            return PropagateData(buf, buf_len);
        }

        int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback)
        {
            DCHECK(write_callback_.is_null());
            if (closed_) {
                if (write_called_after_close_)
                    return ERR_CONNECTION_RESET;
                write_called_after_close_ = true;
                write_callback_ = callback;
                base::ThreadTaskRunnerHandle::Get()->PostTask(
                    FROM_HERE, base::Bind(&FakeDataChannel::DoWriteCallback, weak_factory_.GetWeakPtr()));
                return ERR_IO_PENDING;
            }
            // This function returns synchronously, so make a copy of the buffer.
            data_.push(new DrainableIOBuffer(
                new StringIOBuffer(std::string(buf->data(), buf_len)),
                buf_len));
            base::ThreadTaskRunnerHandle::Get()->PostTask(
                FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback, weak_factory_.GetWeakPtr()));
            return buf_len;
        }

        // Closes the FakeDataChannel. After Close() is called, Read() returns 0,
        // indicating EOF, and Write() fails with ERR_CONNECTION_RESET. Note that
        // after the FakeDataChannel is closed, the first Write() call completes
        // asynchronously, which is necessary to reproduce bug 127822.
        void Close()
        {
            closed_ = true;
            if (!read_callback_.is_null()) {
                base::ThreadTaskRunnerHandle::Get()->PostTask(
                    FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback, weak_factory_.GetWeakPtr()));
            }
        }

    private:
        void DoReadCallback()
        {
            if (read_callback_.is_null())
                return;

            if (closed_) {
                base::ResetAndReturn(&read_callback_).Run(ERR_CONNECTION_CLOSED);
                return;
            }

            if (data_.empty())
                return;

            int copied = PropagateData(read_buf_, read_buf_len_);
            CompletionCallback callback = read_callback_;
            read_callback_.Reset();
            read_buf_ = NULL;
            read_buf_len_ = 0;
            callback.Run(copied);
        }

        void DoWriteCallback()
        {
            if (write_callback_.is_null())
                return;

            CompletionCallback callback = write_callback_;
            write_callback_.Reset();
            callback.Run(ERR_CONNECTION_RESET);
        }

        int PropagateData(scoped_refptr<IOBuffer> read_buf, int read_buf_len)
        {
            scoped_refptr<DrainableIOBuffer> buf = data_.front();
            int copied = std::min(buf->BytesRemaining(), read_buf_len);
            memcpy(read_buf->data(), buf->data(), copied);
            buf->DidConsume(copied);

            if (!buf->BytesRemaining())
                data_.pop();
            return copied;
        }

        CompletionCallback read_callback_;
        scoped_refptr<IOBuffer> read_buf_;
        int read_buf_len_;

        CompletionCallback write_callback_;

        std::queue<scoped_refptr<DrainableIOBuffer>> data_;

        // True if Close() has been called.
        bool closed_;

        // Controls the completion of Write() after the FakeDataChannel is closed.
        // After the FakeDataChannel is closed, the first Write() call completes
        // asynchronously.
        bool write_called_after_close_;

        base::WeakPtrFactory<FakeDataChannel> weak_factory_;

        DISALLOW_COPY_AND_ASSIGN(FakeDataChannel);
    };

    class FakeSocket : public StreamSocket {
    public:
        FakeSocket(FakeDataChannel* incoming_channel,
            FakeDataChannel* outgoing_channel)
            : incoming_(incoming_channel)
            , outgoing_(outgoing_channel)
        {
        }

        ~FakeSocket() override { }

        int Read(IOBuffer* buf,
            int buf_len,
            const CompletionCallback& callback) override
        {
            // Read random number of bytes.
            buf_len = rand() % buf_len + 1;
            return incoming_->Read(buf, buf_len, callback);
        }

        int Write(IOBuffer* buf,
            int buf_len,
            const CompletionCallback& callback) override
        {
            // Write random number of bytes.
            buf_len = rand() % buf_len + 1;
            return outgoing_->Write(buf, buf_len, callback);
        }

        int SetReceiveBufferSize(int32_t size) override { return OK; }

        int SetSendBufferSize(int32_t size) override { return OK; }

        int Connect(const CompletionCallback& callback) override { return OK; }

        void Disconnect() override
        {
            incoming_->Close();
            outgoing_->Close();
        }

        bool IsConnected() const override { return true; }

        bool IsConnectedAndIdle() const override { return true; }

        int GetPeerAddress(IPEndPoint* address) const override
        {
            *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
            return OK;
        }

        int GetLocalAddress(IPEndPoint* address) const override
        {
            *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
            return OK;
        }

        const BoundNetLog& NetLog() const override { return net_log_; }

        void SetSubresourceSpeculation() override { }
        void SetOmniboxSpeculation() override { }

        bool WasEverUsed() const override { return true; }

        bool WasNpnNegotiated() const override { return false; }

        NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }

        bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }

        void GetConnectionAttempts(ConnectionAttempts* out) const override
        {
            out->clear();
        }

        void ClearConnectionAttempts() override { }

        void AddConnectionAttempts(const ConnectionAttempts& attempts) override { }

        int64_t GetTotalReceivedBytes() const override
        {
            NOTIMPLEMENTED();
            return 0;
        }

    private:
        BoundNetLog net_log_;
        FakeDataChannel* incoming_;
        FakeDataChannel* outgoing_;

        DISALLOW_COPY_AND_ASSIGN(FakeSocket);
    };

} // namespace

// Verify the correctness of the test helper classes first.
TEST(FakeSocketTest, DataTransfer)
{
    // Establish channels between two sockets.
    FakeDataChannel channel_1;
    FakeDataChannel channel_2;
    FakeSocket client(&channel_1, &channel_2);
    FakeSocket server(&channel_2, &channel_1);

    const char kTestData[] = "testing123";
    const int kTestDataSize = strlen(kTestData);
    const int kReadBufSize = 1024;
    scoped_refptr<IOBuffer> write_buf = new StringIOBuffer(kTestData);
    scoped_refptr<IOBuffer> read_buf = new IOBuffer(kReadBufSize);

    // Write then read.
    int written = server.Write(write_buf.get(), kTestDataSize, CompletionCallback());
    EXPECT_GT(written, 0);
    EXPECT_LE(written, kTestDataSize);

    int read = client.Read(read_buf.get(), kReadBufSize, CompletionCallback());
    EXPECT_GT(read, 0);
    EXPECT_LE(read, written);
    EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), read));

    // Read then write.
    TestCompletionCallback callback;
    EXPECT_EQ(ERR_IO_PENDING,
        server.Read(read_buf.get(), kReadBufSize, callback.callback()));

    written = client.Write(write_buf.get(), kTestDataSize, CompletionCallback());
    EXPECT_GT(written, 0);
    EXPECT_LE(written, kTestDataSize);

    read = callback.WaitForResult();
    EXPECT_GT(read, 0);
    EXPECT_LE(read, written);
    EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), read));
}

class SSLServerSocketTest : public PlatformTest {
public:
    SSLServerSocketTest()
        : socket_factory_(ClientSocketFactory::GetDefaultFactory())
        , cert_verifier_(new MockCertVerifier())
        , client_cert_verifier_(new MockClientCertVerifier())
        , transport_security_state_(new TransportSecurityState)
        , ct_verifier_(new MockCTVerifier)
        , ct_policy_enforcer_(new MockCTPolicyEnforcer)
    {
    }

    void SetUp() override
    {
        PlatformTest::SetUp();

        cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);
        client_cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);

        server_cert_ = ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
        ASSERT_TRUE(server_cert_);
        server_private_key_ = ReadTestKey("unittest.key.bin");
        ASSERT_TRUE(server_private_key_);

        client_ssl_config_.false_start_enabled = false;
        client_ssl_config_.channel_id_enabled = false;

        // Certificate provided by the host doesn't need authority.
        SSLConfig::CertAndStatus cert_and_status;
        cert_and_status.cert_status = CERT_STATUS_AUTHORITY_INVALID;
        std::string server_cert_der;
        ASSERT_TRUE(X509Certificate::GetDEREncoded(server_cert_->os_cert_handle(),
            &server_cert_der));
        cert_and_status.der_cert = server_cert_der;
        client_ssl_config_.allowed_bad_certs.push_back(cert_and_status);
    }

protected:
    void CreateContext()
    {
        client_socket_.reset();
        server_socket_.reset();
        channel_1_.reset();
        channel_2_.reset();
        server_context_.reset();
        server_context_ = CreateSSLServerContext(
            server_cert_.get(), *server_private_key_, server_ssl_config_);
    }

    void CreateSockets()
    {
        client_socket_.reset();
        server_socket_.reset();
        channel_1_.reset(new FakeDataChannel());
        channel_2_.reset(new FakeDataChannel());
        std::unique_ptr<ClientSocketHandle> client_connection(
            new ClientSocketHandle);
        client_connection->SetSocket(std::unique_ptr<StreamSocket>(
            new FakeSocket(channel_1_.get(), channel_2_.get())));
        std::unique_ptr<StreamSocket> server_socket(
            new FakeSocket(channel_2_.get(), channel_1_.get()));

        HostPortPair host_and_pair("unittest", 0);
        SSLClientSocketContext context;
        context.cert_verifier = cert_verifier_.get();
        context.transport_security_state = transport_security_state_.get();
        context.cert_transparency_verifier = ct_verifier_.get();
        context.ct_policy_enforcer = ct_policy_enforcer_.get();

        client_socket_ = socket_factory_->CreateSSLClientSocket(
            std::move(client_connection), host_and_pair, client_ssl_config_,
            context);
        ASSERT_TRUE(client_socket_);

        server_socket_ = server_context_->CreateSSLServerSocket(std::move(server_socket));
        ASSERT_TRUE(server_socket_);
    }

    void ConfigureClientCertsForClient(const char* cert_file_name,
        const char* private_key_file_name)
    {
        client_ssl_config_.send_client_cert = true;
        client_ssl_config_.client_cert = ImportCertFromFile(GetTestCertsDirectory(), cert_file_name);
        ASSERT_TRUE(client_ssl_config_.client_cert);

        std::unique_ptr<crypto::RSAPrivateKey> key = ReadTestKey(private_key_file_name);
        ASSERT_TRUE(key);

        client_ssl_config_.client_private_key = WrapOpenSSLPrivateKey(
            crypto::ScopedEVP_PKEY(EVP_PKEY_up_ref(key->key())));
    }

    void ConfigureClientCertsForServer()
    {
        server_ssl_config_.client_cert_type = SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;

        ScopedX509NameStack cert_names(
            SSL_load_client_CA_file(GetTestCertsDirectory()
                                        .AppendASCII(kClientCertCAFileName)
                                        .MaybeAsASCII()
                                        .c_str()));
        ASSERT_TRUE(cert_names);

        for (size_t i = 0; i < sk_X509_NAME_num(cert_names.get()); ++i) {
            uint8_t* str = nullptr;
            int length = i2d_X509_NAME(sk_X509_NAME_value(cert_names.get(), i), &str);
            ASSERT_LT(0, length);

            server_ssl_config_.cert_authorities_.push_back(std::string(
                reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
            OPENSSL_free(str);
        }

        scoped_refptr<X509Certificate> expected_client_cert(
            ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName));
        ASSERT_TRUE(expected_client_cert);

        client_cert_verifier_->AddResultForCert(expected_client_cert.get(), OK);

        server_ssl_config_.client_cert_verifier = client_cert_verifier_.get();
    }

    std::unique_ptr<crypto::RSAPrivateKey> ReadTestKey(
        const base::StringPiece& name)
    {
        base::FilePath certs_dir(GetTestCertsDirectory());
        base::FilePath key_path = certs_dir.AppendASCII(name);
        std::string key_string;
        if (!base::ReadFileToString(key_path, &key_string))
            return nullptr;
        std::vector<uint8_t> key_vector(
            reinterpret_cast<const uint8_t*>(key_string.data()),
            reinterpret_cast<const uint8_t*>(key_string.data() + key_string.length()));
        std::unique_ptr<crypto::RSAPrivateKey> key(
            crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
        return key;
    }

    std::unique_ptr<FakeDataChannel> channel_1_;
    std::unique_ptr<FakeDataChannel> channel_2_;
    SSLConfig client_ssl_config_;
    SSLServerConfig server_ssl_config_;
    std::unique_ptr<SSLClientSocket> client_socket_;
    std::unique_ptr<SSLServerSocket> server_socket_;
    ClientSocketFactory* socket_factory_;
    std::unique_ptr<MockCertVerifier> cert_verifier_;
    std::unique_ptr<MockClientCertVerifier> client_cert_verifier_;
    std::unique_ptr<TransportSecurityState> transport_security_state_;
    std::unique_ptr<MockCTVerifier> ct_verifier_;
    std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
    std::unique_ptr<SSLServerContext> server_context_;
    std::unique_ptr<crypto::RSAPrivateKey> server_private_key_;
    scoped_refptr<X509Certificate> server_cert_;
};

// This test only executes creation of client and server sockets. This is to
// test that creation of sockets doesn't crash and have minimal code to run
// under valgrind in order to help debugging memory problems.
TEST_F(SSLServerSocketTest, Initialize)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
}

// This test executes Connect() on SSLClientSocket and Handshake() on
// SSLServerSocket to make sure handshaking between the two sockets is
// completed successfully.
TEST_F(SSLServerSocketTest, Handshake)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(OK, client_ret);
    ASSERT_EQ(OK, server_ret);

    // Make sure the cert status is expected.
    SSLInfo ssl_info;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
    EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status);

    // The default cipher suite should be ECDHE and, unless on NSS and the
    // platform doesn't support it, an AEAD.
    uint16_t cipher_suite = SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
    const char* key_exchange;
    const char* cipher;
    const char* mac;
    bool is_aead;
    SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, cipher_suite);
    EXPECT_STREQ("ECDHE_RSA", key_exchange);
    EXPECT_TRUE(is_aead);
}

// This test makes sure the session cache is working.
TEST_F(SSLServerSocketTest, HandshakeCached)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(OK, client_ret);
    ASSERT_EQ(OK, server_ret);

    // Make sure the cert status is expected.
    SSLInfo ssl_info;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
    EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
    SSLInfo ssl_server_info;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
    EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);

    // Make sure the second connection is cached.
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    TestCompletionCallback handshake_callback2;
    int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());

    TestCompletionCallback connect_callback2;
    int client_ret2 = client_socket_->Connect(connect_callback2.callback());

    client_ret2 = connect_callback2.GetResult(client_ret2);
    server_ret2 = handshake_callback2.GetResult(server_ret2);

    ASSERT_EQ(OK, client_ret2);
    ASSERT_EQ(OK, server_ret2);

    // Make sure the cert status is expected.
    SSLInfo ssl_info2;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
    EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
    SSLInfo ssl_server_info2;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
    EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
}

// This test makes sure the session cache separates out by server context.
TEST_F(SSLServerSocketTest, HandshakeCachedContextSwitch)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(OK, client_ret);
    ASSERT_EQ(OK, server_ret);

    // Make sure the cert status is expected.
    SSLInfo ssl_info;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
    EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
    SSLInfo ssl_server_info;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
    EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);

    // Make sure the second connection is NOT cached when using a new context.
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback2;
    int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());

    TestCompletionCallback connect_callback2;
    int client_ret2 = client_socket_->Connect(connect_callback2.callback());

    client_ret2 = connect_callback2.GetResult(client_ret2);
    server_ret2 = handshake_callback2.GetResult(server_ret2);

    ASSERT_EQ(OK, client_ret2);
    ASSERT_EQ(OK, server_ret2);

    // Make sure the cert status is expected.
    SSLInfo ssl_info2;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
    EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
    SSLInfo ssl_server_info2;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
    EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
}

// This test executes Connect() on SSLClientSocket and Handshake() on
// SSLServerSocket to make sure handshaking between the two sockets is
// completed successfully, using client certificate.
TEST_F(SSLServerSocketTest, HandshakeWithClientCert)
{
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
        kClientCertFileName, kClientPrivateKeyFileName));
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(OK, client_ret);
    ASSERT_EQ(OK, server_ret);

    // Make sure the cert status is expected.
    SSLInfo ssl_info;
    client_socket_->GetSSLInfo(&ssl_info);
    EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status);
    server_socket_->GetSSLInfo(&ssl_info);
    ASSERT_TRUE(ssl_info.cert.get());
    EXPECT_TRUE(client_cert->Equals(ssl_info.cert.get()));
}

// This test executes Connect() on SSLClientSocket and Handshake() twice on
// SSLServerSocket to make sure handshaking between the two sockets is
// completed successfully, using client certificate. The second connection is
// expected to succeed through the session cache.
TEST_F(SSLServerSocketTest, HandshakeWithClientCertCached)
{
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
        kClientCertFileName, kClientPrivateKeyFileName));
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(OK, client_ret);
    ASSERT_EQ(OK, server_ret);

    // Make sure the cert status is expected.
    SSLInfo ssl_info;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
    EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
    SSLInfo ssl_server_info;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
    ASSERT_TRUE(ssl_server_info.cert.get());
    EXPECT_TRUE(client_cert->Equals(ssl_server_info.cert.get()));
    EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
    server_socket_->Disconnect();
    client_socket_->Disconnect();

    // Create the connection again.
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    TestCompletionCallback handshake_callback2;
    int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());

    TestCompletionCallback connect_callback2;
    int client_ret2 = client_socket_->Connect(connect_callback2.callback());

    client_ret2 = connect_callback2.GetResult(client_ret2);
    server_ret2 = handshake_callback2.GetResult(server_ret2);

    ASSERT_EQ(OK, client_ret2);
    ASSERT_EQ(OK, server_ret2);

    // Make sure the cert status is expected.
    SSLInfo ssl_info2;
    ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
    EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
    SSLInfo ssl_server_info2;
    ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
    ASSERT_TRUE(ssl_server_info2.cert.get());
    EXPECT_TRUE(client_cert->Equals(ssl_server_info2.cert.get()));
    EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
}

TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSupplied)
{
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    // Use the default setting for the client socket, which is to not send
    // a client certificate. This will cause the client to receive an
    // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
    // requested cert_authorities from the CertificateRequest sent by the
    // server.

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
        connect_callback.GetResult(
            client_socket_->Connect(connect_callback.callback())));

    scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
    client_socket_->GetSSLCertRequestInfo(request_info.get());

    // Check that the authority name that arrived in the CertificateRequest
    // handshake message is as expected.
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_TRUE(client_cert);
    EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));

    client_socket_->Disconnect();

    EXPECT_EQ(ERR_FAILED, handshake_callback.GetResult(server_ret));
}

TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSuppliedCached)
{
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    // Use the default setting for the client socket, which is to not send
    // a client certificate. This will cause the client to receive an
    // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
    // requested cert_authorities from the CertificateRequest sent by the
    // server.

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
        connect_callback.GetResult(
            client_socket_->Connect(connect_callback.callback())));

    scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
    client_socket_->GetSSLCertRequestInfo(request_info.get());

    // Check that the authority name that arrived in the CertificateRequest
    // handshake message is as expected.
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_TRUE(client_cert);
    EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));

    client_socket_->Disconnect();

    EXPECT_EQ(ERR_FAILED, handshake_callback.GetResult(server_ret));
    server_socket_->Disconnect();

    // Below, check that the cache didn't store the result of a failed handshake.
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    TestCompletionCallback handshake_callback2;
    int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());

    TestCompletionCallback connect_callback2;
    EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
        connect_callback2.GetResult(
            client_socket_->Connect(connect_callback2.callback())));

    scoped_refptr<SSLCertRequestInfo> request_info2 = new SSLCertRequestInfo();
    client_socket_->GetSSLCertRequestInfo(request_info2.get());

    // Check that the authority name that arrived in the CertificateRequest
    // handshake message is as expected.
    EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info2->cert_authorities));

    client_socket_->Disconnect();

    EXPECT_EQ(ERR_FAILED, handshake_callback2.GetResult(server_ret2));
}

TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSupplied)
{
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_TRUE(client_cert);

    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
        kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        connect_callback.GetResult(client_ret));
    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        handshake_callback.GetResult(server_ret));
}

TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSuppliedCached)
{
    scoped_refptr<X509Certificate> client_cert = ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
    ASSERT_TRUE(client_cert);

    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
        kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
    ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        connect_callback.GetResult(client_ret));
    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        handshake_callback.GetResult(server_ret));

    client_socket_->Disconnect();
    server_socket_->Disconnect();

    // Below, check that the cache didn't store the result of a failed handshake.
    ASSERT_NO_FATAL_FAILURE(CreateSockets());
    TestCompletionCallback handshake_callback2;
    int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());

    TestCompletionCallback connect_callback2;
    int client_ret2 = client_socket_->Connect(connect_callback2.callback());

    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        connect_callback2.GetResult(client_ret2));
    EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
        handshake_callback2.GetResult(server_ret2));
}

TEST_F(SSLServerSocketTest, DataTransfer)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    // Establish connection.
    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());
    ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());
    ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);

    client_ret = connect_callback.GetResult(client_ret);
    ASSERT_EQ(OK, client_ret);
    server_ret = handshake_callback.GetResult(server_ret);
    ASSERT_EQ(OK, server_ret);

    const int kReadBufSize = 1024;
    scoped_refptr<StringIOBuffer> write_buf = new StringIOBuffer("testing123");
    scoped_refptr<DrainableIOBuffer> read_buf = new DrainableIOBuffer(new IOBuffer(kReadBufSize), kReadBufSize);

    // Write then read.
    TestCompletionCallback write_callback;
    TestCompletionCallback read_callback;
    server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
        write_callback.callback());
    EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
    client_ret = client_socket_->Read(
        read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
    EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);

    server_ret = write_callback.GetResult(server_ret);
    EXPECT_GT(server_ret, 0);
    client_ret = read_callback.GetResult(client_ret);
    ASSERT_GT(client_ret, 0);

    read_buf->DidConsume(client_ret);
    while (read_buf->BytesConsumed() < write_buf->size()) {
        client_ret = client_socket_->Read(
            read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
        EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
        client_ret = read_callback.GetResult(client_ret);
        ASSERT_GT(client_ret, 0);
        read_buf->DidConsume(client_ret);
    }
    EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed());
    read_buf->SetOffset(0);
    EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));

    // Read then write.
    write_buf = new StringIOBuffer("hello123");
    server_ret = server_socket_->Read(
        read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
    EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
    client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
        write_callback.callback());
    EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);

    server_ret = read_callback.GetResult(server_ret);
    ASSERT_GT(server_ret, 0);
    client_ret = write_callback.GetResult(client_ret);
    EXPECT_GT(client_ret, 0);

    read_buf->DidConsume(server_ret);
    while (read_buf->BytesConsumed() < write_buf->size()) {
        server_ret = server_socket_->Read(
            read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
        EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
        server_ret = read_callback.GetResult(server_ret);
        ASSERT_GT(server_ret, 0);
        read_buf->DidConsume(server_ret);
    }
    EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed());
    read_buf->SetOffset(0);
    EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));
}

// A regression test for bug 127822 (http://crbug.com/127822).
// If the server closes the connection after the handshake is finished,
// the client's Write() call should not cause an infinite loop.
// NOTE: this is a test for SSLClientSocket rather than SSLServerSocket.
TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    // Establish connection.
    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());
    ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());
    ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);

    client_ret = connect_callback.GetResult(client_ret);
    ASSERT_EQ(OK, client_ret);
    server_ret = handshake_callback.GetResult(server_ret);
    ASSERT_EQ(OK, server_ret);

    scoped_refptr<StringIOBuffer> write_buf = new StringIOBuffer("testing123");

    // The server closes the connection. The server needs to write some
    // data first so that the client's Read() calls from the transport
    // socket won't return ERR_IO_PENDING.  This ensures that the client
    // will call Read() on the transport socket again.
    TestCompletionCallback write_callback;
    server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
        write_callback.callback());
    EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);

    server_ret = write_callback.GetResult(server_ret);
    EXPECT_GT(server_ret, 0);

    server_socket_->Disconnect();

    // The client writes some data. This should not cause an infinite loop.
    client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
        write_callback.callback());
    EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);

    client_ret = write_callback.GetResult(client_ret);
    EXPECT_GT(client_ret, 0);

    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
        base::TimeDelta::FromMilliseconds(10));
    base::RunLoop().Run();
}

// This test executes ExportKeyingMaterial() on the client and server sockets,
// after connecting them, and verifies that the results match.
// This test will fail if False Start is enabled (see crbug.com/90208).
TEST_F(SSLServerSocketTest, ExportKeyingMaterial)
{
    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());
    ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());
    ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);

    if (client_ret == ERR_IO_PENDING) {
        ASSERT_EQ(OK, connect_callback.WaitForResult());
    }
    if (server_ret == ERR_IO_PENDING) {
        ASSERT_EQ(OK, handshake_callback.WaitForResult());
    }

    const int kKeyingMaterialSize = 32;
    const char kKeyingLabel[] = "EXPERIMENTAL-server-socket-test";
    const char kKeyingContext[] = "";
    unsigned char server_out[kKeyingMaterialSize];
    int rv = server_socket_->ExportKeyingMaterial(
        kKeyingLabel, false, kKeyingContext, server_out, sizeof(server_out));
    ASSERT_EQ(OK, rv);

    unsigned char client_out[kKeyingMaterialSize];
    rv = client_socket_->ExportKeyingMaterial(kKeyingLabel, false, kKeyingContext,
        client_out, sizeof(client_out));
    ASSERT_EQ(OK, rv);
    EXPECT_EQ(0, memcmp(server_out, client_out, sizeof(server_out)));

    const char kKeyingLabelBad[] = "EXPERIMENTAL-server-socket-test-bad";
    unsigned char client_bad[kKeyingMaterialSize];
    rv = client_socket_->ExportKeyingMaterial(
        kKeyingLabelBad, false, kKeyingContext, client_bad, sizeof(client_bad));
    ASSERT_EQ(rv, OK);
    EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out)));
}

// Verifies that SSLConfig::require_ecdhe flags works properly.
TEST_F(SSLServerSocketTest, RequireEcdheFlag)
{
    // Disable all ECDHE suites on the client side.
    uint16_t kEcdheCiphers[] = {
        0xc007, // ECDHE_ECDSA_WITH_RC4_128_SHA
        0xc009, // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
        0xc00a, // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
        0xc011, // ECDHE_RSA_WITH_RC4_128_SHA
        0xc013, // ECDHE_RSA_WITH_AES_128_CBC_SHA
        0xc014, // ECDHE_RSA_WITH_AES_256_CBC_SHA
        0xc02b, // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        0xc02f, // ECDHE_RSA_WITH_AES_128_GCM_SHA256
        0xcc13, // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
        0xcc14, // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    };
    client_ssl_config_.disabled_cipher_suites.assign(
        kEcdheCiphers, kEcdheCiphers + arraysize(kEcdheCiphers));

    // Require ECDHE on the server.
    server_ssl_config_.require_ecdhe = true;

    ASSERT_NO_FATAL_FAILURE(CreateContext());
    ASSERT_NO_FATAL_FAILURE(CreateSockets());

    TestCompletionCallback connect_callback;
    int client_ret = client_socket_->Connect(connect_callback.callback());

    TestCompletionCallback handshake_callback;
    int server_ret = server_socket_->Handshake(handshake_callback.callback());

    client_ret = connect_callback.GetResult(client_ret);
    server_ret = handshake_callback.GetResult(server_ret);

    ASSERT_EQ(ERR_SSL_VERSION_OR_CIPHER_MISMATCH, client_ret);
    ASSERT_EQ(ERR_SSL_VERSION_OR_CIPHER_MISMATCH, server_ret);
}

} // namespace net
